package com.zoe.vhr.aspect;

import cn.hutool.json.JSONUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @Author Zoe.Zhang
 * @Date: 2021/09/09
 * @Description
 */
@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
    private int count = 0;


    // /**
    //  * 只能在方法上使用
    //  */
    // @Pointcut("@annotation(com.zoe.vhr.annotation.SysLog)")

    /**
     * 可以在类上面使用
     */
    @Pointcut("@within(com.zoe.vhr.annotation.SysLog)")
    public void log() {
    }


    @Around(value = "log()")
    /**
     * 环绕通知: 用得少
     *  需要有返回值，否则接口的返回值返回不到前台;
     *  并且异常要抛出去不能在catch代码中吃掉
     *
     */
    public Object doAround(ProceedingJoinPoint point) throws Throwable {

        Object result = null;
        try {
            String methodName = point.getSignature().getName();
            count++;
            logger.error("{}环绕前通知====", count);

            result = point.proceed();

            count++;
            logger.error("{}环绕后通知; 发生异常不会运行====", count);
        } catch (Throwable throwable) {
            count++;
            logger.error("{}环绕通知catch; 发生异常会执行;异常必须要抛出====", count);
            throw throwable;
        }
        return result;
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        count++;
        logger.error("{}方法执行前通知====", count);
    }


    /**
     * 返回后通知
     *
     * @param joinPoint
     * @param result
     */
    @AfterReturning(value = "log()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        count++;
        // 获取请求参数
        Object[] args = joinPoint.getArgs();
        // 方法签名
        Signature signature = joinPoint.getSignature();
        // 获取类名
        String declaringTypeName = signature.getDeclaringTypeName();
        // 返回方法名
        String methodName = signature.getName();
        logger.error("{}方法返回后通知", count);
        logger.info("返回值==>{}", JSONUtil.toJsonStr(result));
    }

    /**
     * 方法运行后通知
     *
     * @param joinPoint
     */
    @After(value = "log()")
    public void doAfter(JoinPoint joinPoint) {
        count++;
        logger.error("{}方法运行后通知====", count);
    }


    @AfterThrowing(value = "log()", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
        count++;
        // 获取请求参数
        Object[] args = joinPoint.getArgs();
        // 方法签名
        Signature signature = joinPoint.getSignature();
        // 获取类名
        String declaringTypeName = signature.getDeclaringTypeName();
        // 返回方法名
        String methodName = signature.getName();
        logger.error("{}异常通知===>{}", count, ex.getMessage());
    }
}
